package com.zhousb.file_retrieval_server.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;
import com.zhousb.file_retrieval_server.domain.bo.UploadBo;
import com.zhousb.file_retrieval_server.domain.entity.CrContract;
import com.zhousb.file_retrieval_server.domain.entity.CrContractFiles;
import com.zhousb.file_retrieval_server.domain.so.ContractPageSo;
import com.zhousb.file_retrieval_server.domain.vo.ContractPageVo;
import com.zhousb.file_retrieval_server.domain.dto.UploadFileDto;
import com.zhousb.file_retrieval_server.mapper.CrContractFilesMapper;
import com.zhousb.file_retrieval_server.mapper.CrContractMapper;
import com.zhousb.file_retrieval_server.service.ContractService;
import com.zhousb.file_retrieval_server.service.SysUserService;
import com.zhousb.file_retrieval_server.utils.AuthUtils;
import com.zhousb.file_retrieval_server.utils.IdGenerator;
import com.zhousb.file_retrieval_server.utils.OSSUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ZhouShenBin
 * @date 2024/9/24 16:21
 * @description
 */
@Service
public class ContractServiceImpl implements ContractService {
    @Resource
    private CrContractMapper crContractMapper;
    @Resource
    private CrContractFilesMapper crContractFilesMapper;
    @Resource
    private SysUserService sysUserService;
    @Resource
    AuthUtils authUtils;
    @Resource
    OSSUtil ossUtil;

    @Override
    public IPage<ContractPageVo> page(Page<?> page, ContractPageSo so) {
        Long ownUserId = null;
        if (!authUtils.isSuperAdmin()) {
            ownUserId = authUtils.getUser().getUserId();
        }
        List<String> keywords = new ArrayList<>();
        if (StringUtils.hasText(so.getKeyword())) {
            keywords = Arrays.asList(so.getKeyword().split(" "));
        }
        IPage<ContractPageVo> result = crContractMapper.page(page, so, keywords, ownUserId);
        result.getRecords().forEach(item -> item.setOwnUserName(sysUserService.getRealName(item.getOwnUserName())));
        return result;
    }

    @Override
    public boolean upload(UploadBo bo) throws DocumentException, FileNotFoundException {
        CrContract crContract = new CrContract();
        Long contractId = IdGenerator.nextId();
        crContract.setId(contractId);
        crContract.setOwnUserId(Long.parseLong(bo.getUserId()));
        crContract.setContractName(bo.getContractName());
        crContract.setContractTime(bo.getContractTime());
        crContract.setUploadTime(LocalDateTime.now());
        crContractMapper.insert(crContract);

        List<UploadFileDto> files = bo.getFiles();
        boolean isImages = true;
        for (UploadFileDto file : files) {
            if (file.getFileType().equalsIgnoreCase("pdf")) {
                isImages = false;
                break;
            }
        }
        if (isImages) {
            //合并成pdf
            CrContractFiles contractFile = new CrContractFiles();
            contractFile.setId(IdGenerator.nextId());
            contractFile.setContractId(contractId);
            contractFile.setFileName(bo.getContractName().concat(".pdf"));
            contractFile.setFileType("pdf");

            String fileName = bo.getContractName().concat(".pdf");
//            File file = new File(bo.getContractName().concat(".pdf"));
            List<String> imagePathList = new ArrayList<>();
            imagePathList = files.stream().map(UploadFileDto::getFileUrl).collect(Collectors.toList());
            File file = imageToPdf(imagePathList, fileName);
            InputStream inputStream = new FileInputStream(file);
            String ossUrl = ossUtil.updateByInputStream(inputStream, ".pdf");
            contractFile.setFileSize(String.format("%.2f", (double) file.length() / 1048576d) + "M");
            contractFile.setFileUrl(ossUrl);
            crContractFilesMapper.insert(contractFile);
        } else {
            //存在pdf，直接存储
            for (UploadFileDto file : files) {
                CrContractFiles contractFile = new CrContractFiles();
                contractFile.setId(IdGenerator.nextId());
                contractFile.setContractId(contractId);
                contractFile.setFileName(file.getFileName());
                contractFile.setFileType(file.getFileType());
                contractFile.setFileSize(file.getFileSize());
                contractFile.setFileUrl(file.getFileUrl());
                crContractFilesMapper.insert(contractFile);
            }
        }
        return false;
    }

    @Override
    public UploadFileDto uploadFile(MultipartFile file) throws IOException {
//        List<UploadFileVo> fileList = new ArrayList<>();
//        for (MultipartFile file : files) {
        UploadFileDto vo = new UploadFileDto();
        InputStream inputStream = file.getInputStream();
        String fileName = file.getOriginalFilename();
        if (!StringUtils.hasText(fileName)) {
            return null;
        }
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        String ossUrl = ossUtil.updateByInputStream(inputStream, suffix);
        vo.setFileName(fileName);
        vo.setFileType(suffix.substring(1));
        vo.setFileSize(String.format("%.2f", (double) file.getSize() / 1048576d) + "M");
        vo.setFileUrl(ossUrl);
        return vo;
//            fileList.add(vo);
//        }
//        return fileList;
    }


    public File imageToPdf(List<String> imageUrllist, String mOutputPdfFileName) throws DocumentException {

        String TAG = "PdfManager";
        Document doc = new Document(PageSize.A4, 20, 20, 20, 20);
        try {
            PdfWriter.getInstance(doc, new FileOutputStream(mOutputPdfFileName));
            doc.open();
            for (int i = 0; i < imageUrllist.size(); i++) {
                doc.newPage();
//                doc.add(new Paragraph("简单使用iText"));
                URL url = ossUtil.getFileUrl(imageUrllist.get(i).substring(imageUrllist.get(i).lastIndexOf("/") + 1));
                Image png1 = Image.getInstance(url);
                float heigth = png1.getHeight();
                float width = png1.getWidth();
                int percent = getPercent2(heigth, width);
                png1.setAlignment(Image.MIDDLE);
                png1.scalePercent(percent + 3);// 表示是原来图像的比例;
                doc.add(png1);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            doc.close();
        }
        File mOutputPdfFile = new File(mOutputPdfFileName);
        if (!mOutputPdfFile.exists()) {
            mOutputPdfFile.deleteOnExit();
            return null;
        }
        return mOutputPdfFile;
    }

    /**
     * 第一种解决方案 在不改变图片形状的同时，判断，如果h>w，则按h压缩，否则在w>h或w=h的情况下，按宽度压缩 * * @param h * @param w * @return
     */
    private int getPercent(float h, float w) {
        int p = 0;
        float p2 = 0.0f;
        if (h > w) {
            p2 = 297 / h * 100;
        } else {
            p2 = 210 / w * 100;
        }
        p = Math.round(p2);
        return p;
    }

    /**
     * 第二种解决方案，统一按照宽度压缩 这样来的效果是，所有图片的宽度是相等的，自我认为给客户的效果是最好的 * * @param
     */
    private int getPercent2(float h, float w) {
        int p = 0;
        float p2 = 0.0f;
        p2 = 530 / w * 100;
        p = Math.round(p2);
        return p;
    }
}
